/******************************************************************************
 * SAGE - Scalable Adaptive Graphics Environment
 *
 * Module: streamProtocol.h
 * Author : Byungil Jeong, Rajvikram Singh
 * Description: This is the header file for the stream protocol modules of SAGE. 
 *       It gives the interface to be provided by all the protocols included.
 * Notes : This is based on the TeraVision network protocol.
 *	
 * Copyright (C) 2004 Electronic Visualization Laboratory,
 * University of Illinois at Chicago
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either Version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser Public License along
 * with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Direct questions, comments etc about SAGE to bijeong@evl.uic.edu or 
 * http://www.evl.uic.edu/cavern/forum/
 *
 *****************************************************************************/
 
#ifndef _STREAM_PROTOCOL_H
#define _STREAM_PROTOCOL_H

#include "sageBase.h"
#include <stack>

#define REG_MSG_SIZE 	128
#define TRANSFER_RATE_CONVERGE 9

class sageNwConfig {
public:
	int rcvBufSize;
	int sendBufSize;
	int mtuSize;
	
	//sageNwConfig() : rcvBufSize(65536), sendBufSize(65536), mtuSize(1450) {}
	sageNwConfig() : rcvBufSize(8000000), sendBufSize(8000000), mtuSize(1450) {}
}; 

class streamProtocol{

protected:
	sageStreamMode sMode;
	int rcvPort;
	sageNwConfig config;
	std::vector<int> rcvList;
	std::vector<int> sendList;
	std::vector<bool> sendAck;
	
	int checkInterval, blockCnt;
	double prevTime, transferRate, curRate, curMaxRate;
	long totalTransfer;
	bool closeFlag;
	
	int maxTransfer, minTransfer;
	std::stack<double> maxRateStack;
			
	int checkSendRate();
	static void* controlThread(void *args);
	
public:		
	int init(sageStreamMode m, int p, sageNwConfig &c);	
					// The 1st parameter is the mode of operartion
					// The 2nd parameter is the receiver port. If a receiver cannot be
					// started at this port, a false should be returned. 
					// The 3rd parameter is configuration info
	int initFlowControl(int interval, int min, int max);
	int activateFlowControl();
	
	int setConfig(sageNwConfig c) { config = c; }
					// set network configurations for new network connections
	
	int duplicate(sageApiOption op); // only for SAGE_BRIDGE
					// receive a sage-block, duplicate and send it to all receivers

	virtual int controlSendingRate() = 0;
	
	virtual int checkConnections(char *msg) = 0; // for SAGE_RCV or SAGE_BRIDGE mode
					// checking if there is a new sender trying to connect
					// if yes, create a new connection and return the sender ID
					// if no, return -1
					// memory bigger than REG_MSG_SIZE should be allocated to msg
					
	virtual int connect(char* ip, char *msg) = 0; // for SAGE_SEND or SAGE_BRDIGE mode
					// This function blocks till it connects (or cannot connect)
					// create a connection to a receiver					
					// and return the receiver ID
					// the length of string msg should not exceed REG_MSG_SIZE
					
	virtual int recv(int id, sageBlock *sb, sageApiOption op) = 0;	
					// id : sender ID, sb : sageBlock, op : blocking or non-blocking
					
	virtual int send(int id, sageBlock *sb, sageApiOption op) = 0;
					// id : receiver ID, sb : sageBlock, op : blocking or non-blocking
	virtual int	send(int id, sageChildBlock *sb, sageApiOption op) = 0;
	
	virtual int close() = 0;	// When called, it is expected to close all internal sockets and force any operation
					// (send/recv) to be interrupted. If this function is not called explicitly the destructor is supposed
					// to call it before cleaning up
						

        virtual int recv(int id, sageAudioBlock *sb, sageApiOption op);
        virtual int send(int id, sageAudioBlock *sb, sageApiOption op);

};

#endif
